/*
 * EX_SLIST.h
 *
 *  Created on: 2012-5-18
 *      Author: fnn
 *
 *
 * A singly-linked list is headed by a single forward pointer. The elements
 * are singly linked for minimum space and pointer manipulation overhead at
 * the expense of O(n) removal for arbitrary elements. New elements can be
 * added to the list after an existing element or at the head of the list.
 * Elements being removed from the head of the list should use the explicit
 * macro for this purpose for optimum efficiency. A singly-linked list may
 * only be traversed in the forward direction.  Singly-linked lists are ideal
 * for applications with large datasets and few or no removals or for
 * implementing a LIFO queue.
 *
 */

#ifndef _EX_SLIST_H_
#define _EX_SLIST_H_


/*
 * Singly-linked List definitions.
 */
#define EX_SLIST_HEAD(name, type)						\
struct name {								\
	struct type *slh_first;	/* first element */			\
}

#define	EX_SLIST_HEAD_INITIALIZER(head)					\
	{ NULL }

#define EX_SLIST_ENTRY(type)						\
struct {								\
	struct type *sle_next;	/* next element */			\
}

/*
 * Singly-linked List access methods.
 */
#define	EX_SLIST_FIRST(head)	((head)->slh_first)
#define	EX_SLIST_END(head)		NULL
#define	EX_SLIST_EMPTY(head)	(EX_SLIST_FIRST(head) == EX_SLIST_END(head))
#define	EX_SLIST_NEXT(elm, field)	((elm)->field.sle_next)

#define	EX_SLIST_FOREACH(var, head, field)					\
	for((var) = EX_SLIST_FIRST(head);					\
	    (var) != EX_SLIST_END(head);					\
	    (var) = EX_SLIST_NEXT(var, field))

/*
 * Singly-linked List functions.
 */
#define	EX_SLIST_INIT(head) {						\
	EX_SLIST_FIRST(head) = EX_SLIST_END(head);				\
}

#define	EX_SLIST_INSERT_AFTER(EX_SLISTelm, elm, field) do {			\
	(elm)->field.sle_next = (EX_SLISTelm)->field.sle_next;		\
	(EX_SLISTelm)->field.sle_next = (elm);				\
} while (0)

#define	EX_SLIST_INSERT_HEAD(head, elm, field) do {			\
	(elm)->field.sle_next = (head)->slh_first;			\
	(head)->slh_first = (elm);					\
} while (0)

#define	EX_SLIST_REMOVE_HEAD(head, field) do {				\
	(head)->slh_first = (head)->slh_first->field.sle_next;		\
} while (0)



#endif /* _EX_SLIST_H_ */
